<?php
/**
 * @author jonathan poelen <jonathan.poelen@gmail.com>
 * @version 1.0: jo_link_noir
 * @date 13-01-2010
 */
abstract class SW_Dependency
{
	/** @var array*/
	static private $_dependencies;


	/**
	 * Si l'instance n'existe pas, static::create est utilisé
	 * @param string $instance
	 * @param mixed $param = null
	 * @return SW_Dependancy
	 * @exception SW_Exception_Dependence 'No dependence of '.$instance
	 */
	static public function factory($instance, $param = null)
	{
		if (isset(self::$_dependencies[$instance]))
			return self::$_dependencies[$instance];

		if (!($dependency = new static($param, $instance)))
			throw new RuntimeException('No dependency '.$instance);
		if ($dependency->isCached())
			$_dependencies[$instance] = $dependency;
		return $dependency;
	}

	/**
	 * @param string $key
	 * @return bool
	 */
	static public function exist($key)
	{
		return isset(self::$_dependencies[$key]);
	}

	/**
	 * @param string $key
	 * @return SW_Dependency | null
	 */
	static public function get($key)
	{
		return isset(self::$_dependencies[$key]) ? self::$_dependencies[$key] : null;
	}

	/**
	 * @param string $key
	 * @param SW_Dependance $dependence
	 * @return SW_Dependency
	 */
	static public function set($key, SW_Dependency $dependence)
	{
		return self::$_dependencies[$key] = $dependence;
	}

	/**
	 * Retourne le $_dependencies
	 * @return array : {key_cache => SW_Dependency | null, ...}
	 */
	static public function gets()
	{
		return self::$_dependencies;
	}


	/** @var array = null : {id_asset => {id_type => {id_group, ...}, ...}, ...}*/
	protected $unblock = null;

	/** @var array = null : {group_element => group_element, ...}*/
	protected $required = null;

	protected $cached = true;

	/**
	 * @return bool
	 */
	final public function isCached()
	{
		return $this->cached;
	}

	/**
	 * Retourne un tableau des nouveaux élements débloqué
	 * @return array
	 */
	final public function getUnblock()
	{
		return $this->unblock;
	}

	/**
	 * Retourne un tableau des élements obligatoire et non débloqué
	 * @return array :{group_element => group_element, ...}
	 */
	final public function getRequired()
	{
		return $this->required;
	}

	/**
	 * @param SW_Planet_Storage_Treatment $element
	 * @param array& $unblock = null
	 * @param array& $required = null
	 */
	public function affectSolve(SW_Planet_Storage_Treatment $element, array &$unblock = null, array &$required = null)
	{
		$this->unblock = &$unblock;
		$this->required = &$required;
		$this->solve($element);
		unset($this->unblock, $this->required);
		$this->unblock = $this->required = null;
	}

	/**
	 * Calcule le tableau des dépendances
	 * @param SW_Planet_Storage_Treatment $element
	 */
	abstract protected function solve(SW_Planet_Storage_Treatment $element);
}